from datetime import datetime
from collections import defaultdict
import math
__author__ = 'pstalidis'
from SocialChurning.SpreadActivation import SpreadActivation


start_of_monitoring = datetime(year=2008, month=07, day=20)
end_of_period1 = datetime(year=2008, month=10, day=20)
end_of_period2 = datetime(year=2008, month=11, day=19)

strength = "strength"
energy = "energy"

# path = "/home/pstalidis/Downloads/"
path = "/home/panagiotis/Projects/ICT4Growth/SocialChurning/"
name1 = "facebook-wosn-wall/out.facebook-wosn-wall"
name2 = "facebook-wosn-links/out.facebook-wosn-links"

orfile = open(path+name2, 'rb')
orfile.readline()
orfile.readline()

G = SpreadActivation()

# # add friendship links
# for line in orfile:
#     lst = line.strip().split()
#     G.add_edge(int(lst[0]), int(lst[1]), weight=0)
#     # G.add_edge(int(lst[1]), int(lst[0]), weight=0)
#
# orfile.close()

active = defaultdict(set)
# for every wall post add an edge to the graph from poster to wall owner
orfile = open(path+name1, 'rb')
orfile.readline()
orfile.readline()
for line in orfile:
    data = line.strip().split()
    stamp = datetime.fromtimestamp(int(data[3]))
    if stamp > start_of_monitoring:
        if stamp > end_of_period2:
            active["period3"].add(int(data[0]))
        else:
            try:
                G.edge[int(data[0])][int(data[1])][strength] += float(data[2])
            except KeyError:
                G.add_edge(int(data[0]), int(data[1]), {strength: float(data[2])})
            try:
                G.edge[int(data[1])][int(data[0])][strength] += float(data[2])
            except KeyError:
                G.add_edge(int(data[1]), int(data[0]), {strength: float(data[2])})
            if stamp > end_of_period1:
                active["period2"].add(int(data[0]))
            else:
                active["period1"].add(int(data[0]))

orfile.close()

# remove posts to self wall
G.remove_edges_from(G.selfloop_edges())

print "removing sparse nodes"

# inactive_nodes = [u for u in G.nodes() if G.out_degree(u, weight="strength") < 11]
# G.remove_nodes_from(inactive_nodes)

G.normalize_weights(strength=strength)

print "removing dead links"
for (u1, u2, d) in G.edges(data=True):
    try:
        if d[strength] == 0:
            G.remove_edge(u1, u2)
    except KeyError:
        print "KeyError in edge", u1, u2, d

print "detecting churners"
# active["period1"] -= set(inactive_nodes)
# active['period2'] -= set(inactive_nodes)
# active['period3'] -= set(inactive_nodes)
first_churners = active["period1"] - active['period2']
second_churners = set(G.nodes()) - active["period3"]

problematic = (active["period1"] & active["period3"]) - active['period2']

print 5*"-", " dataset statistics ", 5*"-"
print "active users in monitoring period", len(active["period1"])
print "active users in first churn detection period", len(active['period2'])
print "first churners", len(first_churners), " (active in monitoring period but not in churn detection period)"
print "active users in second churn detection period", len(active['period3'])
print "second churners", len(second_churners),
print " (active in monitoring period and first churn period, but not in second churn period)"
print "total number of users in experiment", len(active["period1"] | active["period2"] | active["period3"])
print "problematic users (active in monitoring period and second churn period but not in first churn period)",
print len(problematic)
print 30*"-"

from matplotlib import pyplot as plt

Xs = [[0.0, 100.0]]
Ys = [[0.0, 100.0]]
Zs = [[0.0, 0.0]]
labels = ["random"]
print "running spreading activation"
for sp in [0.01, 0.05, 0.07, 0.1, 0.15]:
    results = dict()
    # sp *= 0.05
    # G.setup_energy(first_churners, initial_energy=1.0, energy=energy)
    G.setup_energy(first_churners, initial_energy=1.0, energy=energy)
    G.predict(spreading_factor=sp, accuracy_threshold=0.01, activation_threshold=0,
              strength=strength, energy=energy, max_iter=15)
    A = [x for (x, c) in G.most_common() if x not in first_churners]
    T = [1 if y in second_churners else 0 for y in A]
    R = [int(i*0.01*len(A)) for i in xrange(1, 51)]
    Xs.append([(100.0 * (float(len(set(A[:x]))) / G.number_of_nodes())) for x in R])
    Ys.append([(100.0 * (float(len(second_churners & set(A[:x]))) / len(second_churners))) for x in R])
    Zs.append([(100.0 * float(sum(T[:x])) / x) for x in R])
    labels.append("d "+str(sp))

plt.figure(1)
for i in xrange(0, len(Ys)):
    plt.plot(Xs[i], Ys[i], label=labels[i])
plt.xlabel('Percent of Subscribers')
plt.ylabel('Percent of Churners')
plt.grid(True)
plt.legend(loc="upper right")
plt.axis([0, 100, 0, 100])
# plt.show()

# plt.figure(2)

for i in xrange(0, len(Zs)):
    plt.plot(Xs[i], Zs[i])
plt.xlabel('Percent of Subscribers')
plt.ylabel('Hit Rate')
plt.axis([0, 100, 0, 100])

plt.show()
